/*
 * Copyright (C) 2010 Johan Waldeback
 *  
 * This file is part of the OpenFMS project (http://www.openfms-project.org)
 * 
 * OpenFMS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


#include "GraphDataSet.h"
#include <wx/wx.h>
#include <cassert>

/**
 * OpenFms::GraphDataSet constructor.
 */
GraphDataSet::GraphDataSet( ) : m_pX(NULL), m_pY(NULL), m_count(0)
{

}

/**
 * OpenFms::GraphDataSet constructor.
 */
GraphDataSet::GraphDataSet( const float *pX, const float *pY, size_t count )
{
	this->setData(pX, pY, count);
}

/**
 * Set data points
 *
 * @param pX Pointer to a list of x-values to use.
 * @param pY Pointer to a list of y-values to use.
 * @param count Number of points to store.
 */
void GraphDataSet::setData( const float *pX, const float *pY, size_t count )
{
	// free any previously allocated memory
	if(m_pX) delete m_pX;
	if(m_pY) delete m_pY;

	// Allocate memory and copy all data values.
	m_pX = new float[count];
	m_pY = new float[count];
	memcpy( m_pX, pX, count*sizeof(float));
	memcpy( m_pY, pY, count*sizeof(float));

	// copy the length of the arrays
	m_count = count;
}

/**
 * OpenFms::GraphDataSet destructor.
 */
GraphDataSet::~GraphDataSet( )
{
	if( this->m_pX ) delete this->m_pX;
	if( this->m_pY ) delete this->m_pY;
	//setWxPointListLength(0);
}

/**
 * Get maximum absolute value from an array of values
 *
 * @param pValues Pointer to the array of values to examine
 * @param count Number of values to examine
 * @return Returns the maximum absolute value in the array
 */
static float getMaxAbs( const float *pValues , size_t count )
{
	// check input arguments
	// retrun 0 if no values are given
	if( pValues == NULL || count <= 0 ) return 0.f;

	// Iterate throught the list of values and store the max abs value found
	float max = 0.f;
	for( size_t i=0; i<count; ++i ) {
		if( pValues[i] > max ) max = pValues[i];
		if( pValues[i] < -max ) max = -pValues[i];
	}

	// retrun the max abs value found
	return max;
}

/**
 * Get the maxumim absolute value in the x-value list
 * @return The maximum absolute value found in the x-value list.
 */
float GraphDataSet::getMaxAbsX()
{
	return getMaxAbs( m_pX, m_count );
}
/**
 * Get the maxumim absolute value in the y-value list
 * @return The maximum absolute value found in the y-value list.
 */
float GraphDataSet::getMaxAbsY()
{
	return getMaxAbs( m_pY, m_count );
}

/**
 * Resizes the storage used by list that contains the scaled data points
 * @note Calling this function with the argument zero, will free all memory
 * used by this list.
 * @param length The lenght to resize the array to.
 */
void GraphDataSet::setWxPointListLength(size_t length)
{
	// If the length is smaller: Delete the whole list to zero length
	// (Which is later on expanded to the correct length)
	while( m_wxPointList.GetCount() > length ) {
		m_wxPointList.DeleteContents(true);
		m_wxPointList.DeleteNode( m_wxPointList.GetLast() );
	}

	// If the list is smaller than requested, append new dummiepoints to 
	// the list until the corrent lenght is reached.
	while( m_wxPointList.GetCount() < length ) {
		m_wxPointList.Append(new wxPoint(0,0));
	}

	// update the point count
	m_count = length;
}

/**
 * Update/rescale the scaled list.
 * 
 * Takes the points in the real/actual data point list, resizes them and 
 * stored the result in the scaled points list.
 *
 * @param scaleX Scale factor to use in the x-direction
 * @param scaleY Scale factor to use in the y-direction.
 * @return Returns a pointer to the scales points list.
 */
wxPointList *GraphDataSet::getScaledWxPointList( float scaleX, float scaleY )
{
	// make sure the list has the correct length
	this->setWxPointListLength(m_count);

	// calculate tht values
	for( size_t i=0; i<m_count; ++i ) {
		m_wxPointList[i]->x = this->m_pX[i] * scaleX;
		m_wxPointList[i]->y = this->m_pY[i] * scaleY;
	}

	// return the list
	return &this->m_wxPointList;
}
